#include <iostream>
#include <mutex>
#include <atomic>
#include <condition_variable>
using namespace std;

#define SELECT_MODE 2

#if SELECT_MODE == 0
// 定义一个单例模式的任务队列,饿汉模式
class TaskQueue {
    public:
    TaskQueue(const TaskQueue& t) = delete;
    TaskQueue& operator=(const TaskQueue& t) = delete;
    static TaskQueue* getInstance() {
        return m_taskQ;
    }

    void print() {
        cout<<"单例对象的一个成员函数..."<<endl;
    }

    private:
    TaskQueue() = default;
    // TaskQueue(const TaskQueue& t) = default;
    // TaskQueue& operator=(const TaskQueue& t) = default;
    static TaskQueue* m_taskQ;
};
TaskQueue* TaskQueue::m_taskQ = new TaskQueue;

#elif SELECT_MODE == 1

// 定义一个单例模式的任务队列,懒汉模式
class TaskQueue {
public:
    TaskQueue(const TaskQueue& t) = delete;
    TaskQueue& operator=(const TaskQueue& t) = delete;
    static TaskQueue* getInstance() {
        TaskQueue* task = m_taskQ.load();
        if (task == nullptr) {  // 双重检查锁定
            m_mutex.lock();
            task = m_taskQ.load();
            if (task == nullptr) {
                task = new TaskQueue;
                m_taskQ.store(task);
            }
            m_mutex.unlock();
        }
        return task;
    }

    void print() {
        cout<<"单例对象的一个成员函数..."<<endl;
    }

private:
    TaskQueue() = default;
    // TaskQueue(const TaskQueue& t) = default;
    // TaskQueue& operator=(const TaskQueue& t) = default;
    // 只能通过类名访问静态属性或方法
    // static TaskQueue* m_taskQ;
    static mutex m_mutex;
    static atomic<TaskQueue*> m_taskQ;
};
// TaskQueue* TaskQueue::m_taskQ = nullptr;
atomic<TaskQueue*> TaskQueue::m_taskQ{nullptr};
mutex TaskQueue::m_mutex;

#elif SELECT_MODE == 2
// 定义一个单例模式的任务队列,懒汉模式
// 使用静态的局部对象解决线程安全问题 ->C++11
class TaskQueue {
public:
    TaskQueue(const TaskQueue& t) = delete;
    TaskQueue& operator=(const TaskQueue& t) = delete;
    static TaskQueue* getInstance() {
        static TaskQueue task;
        return &task;
    }

    void print() {
        cout<<"单例对象的一个成员函数..."<<endl;
    }

private:
    TaskQueue() = default;
    // TaskQueue(const TaskQueue& t) = default;
    // TaskQueue& operator=(const TaskQueue& t) = default;
};

#endif

int main() {

    TaskQueue* taskQ = TaskQueue::getInstance();
    taskQ->print();

    return 0;
}

